package productions;

import exceptions.ParserException;
import lexico.ErrorTable;
import lexico.SymbolTable;
import lexico.TokenClass;

/**
 * @author heekinho
 */
public class DeclarationsProduction extends AbstractProductionRule {
    /* Muitos dos métodos irão precisar de algo assim: */

    private static DeclarationsProduction instance = new DeclarationsProduction();

    public static DeclarationsProduction getInstance() {
        return instance;
    }

    /**
     * Regra: declarations : (constante | tipo_definido | (variaveis ';'))*;
     * @return
     * @throws ParserException
     */
    @Override
    public boolean analyze(SymbolTable st, ErrorTable et) throws ParserException {
        while (!st.eof() && first.contains(st.getCurrent().getTokenClass())) {
            if (ConstanteProduction.getInstance().analyze(st, et)) {
                continue;
            }
            if (TipoDefinidoProduction.getInstance().analyze(st, et)) {
                continue;
            }
            if (VariaveisProduction.getInstance().analyze(st, et)) {
                if (basicParse(st, TokenClass.DELIMITER_SEMICOLON)) {
                    continue;
                }
                return skipUntilSynchronize(st, et, "Era esperado um ';'.");
            }

            return false;
        }

        return true;
    }

    @Override
    protected void populateFirst() {
        //from constante
        first.add(TokenClass.KEYWORD_CONSTANTES);

        //from tipodefinido
        first.add(TokenClass.KEYWORD_TIPO);

        //from variaveis
        first.add(TokenClass.KEYWORD_VARIAVEIS);
    }

    @Override
    protected void populateFollow() {
       //from principal
       follow.add(TokenClass.KEYWORD_FUNCAO);
    }

}
